#ifndef __NB_H_
#define __NB_H_
#include "zos_def.h"


/*******************************************************************************
 *                             Type definitions                                *
 ******************************************************************************/

typedef enum
{
    NB_STATE_POWER_ON = 0,  ///  正常开机
    NB_STATE_PIN_RESET,     ///  RESET硬件复位
    NB_STATE_SOFT_RESET,    ///  软件复位
    NB_STATE_UTC_WAKEUP,    ///  RTC超时唤醒
    NB_STATE_EXTPIN_WAKEUP, ///  WAKEUP-PIN 唤醒
    NB_STATE_WDT_RESET,     ///  硬件看门狗复位
    NB_STATE_UNKNOWN_ON,    ///  未知错误，请查看硬件设计
} NB_START_STATE;


typedef enum
{
    NB_RB_BY_ASSERT = 0,	//ASSERT断言错误复位
    NB_RB_BY_NRB,			//软件复位 来自AT+NRB/nb_reboot/....
    NB_RB_BY_RESET,			//软件复位 来自恢复出厂设置 AT+RESET
    NB_RB_BY_POWERTEST,		//软件复位 by	AT+NV=POWERTEST,unused
    NB_RB_BY_FOTA,			//软件复位 by  FOTA
    NB_RB_BY_LOW_VOL,		//低电压复位 by nb_vbat_low_check for low vBAT
    NB_RB_MAX,
} NB_REBOOT_TYPE_T;


typedef enum
{
	NB_SIM_TYPE_UNKNOWN = 0,
	NB_SIM_TYPE_TELECOM, //telecom
	NB_SIM_TYPE_MOBILE,  //mobile
	NB_SIM_TYPE_UNICOM,  //unicom
} NB_SIM_card_type_t;

// typedef enum {
// 	OS_OK					        =  0,
// 	OS_ERR					      = -1, 		  //normal err
// 	OS_Err_Timeout			  = -2, 		  // Operation not completed within the timeout period.
// 	OS_Err_NoConnected		= -3, 		  // tcpip newwork unusable,such as  PDP not activate
// 	OS_Err_Parameter		  = -4, 		  // input parameter error.
// 	OS_Err_NoMemory 		  = -5, 		  // System is out of memory: it was impossible to allocate or reserve memory for the operation.
// 	OS_Err_NotAllowed		  = -6, 		  // api not allowed,such as SIM card not insert,and do something about 3GPP operation.
// 	OS_Err_LowVbat			  = -7, 		  //low Vbat,can not do flash write
// 	OS_Err_Reserved 		  = 0x7FFFFFFF
// } os_ret_Status_t;


typedef struct nb_serving_cell_info
{
	int Signalpower;
	int Totalpower;
	int TXpower;
	int CellID;
	int ECL;
	int SNR;
	int EARFCN;
	int PCI;
	int RSRQ;
	char tac[5];
	int sband;
} nb_serving_cell_info_t;

typedef struct nb_phy_info
{
	//BLER
	int RLC_UL_BLER;
	int RLC_DL_BLER;
	int MAC_UL_BLER;
	int MAC_DL_BLER;
	int MAC_UL_total_bytes;
	int MAC_DL_total_bytes;
	int MAC_UL_total_HARQ_TX;
	int MAC_DL_total_HARQ_TX;
	int MAC_UL_HARQ_re_TX;
	int MAC_DL_HARQ_re_TX;
	//THP
	int RLC_UL_tput;
	int RLC_DL_tput;
	int MAC_UL_tput;
	int MAC_DL_tput;
} nb_phy_info_t;

typedef struct net_neighbor_cell_info
{
	int nc_earfcn;
	int nc_pci;
	int nc_rsrp;
} net_neighbor_cell_info_t;

typedef struct nb_neighbor_cell_info
{
	int nc_num;
	net_neighbor_cell_info_t neighbor_cell_info[5];
} nb_neighbor_cell_info_t;

typedef struct nb_radio_info
{
	nb_serving_cell_info_t serving_cell_info;
	nb_neighbor_cell_info_t neighbor_cell_info;
	nb_phy_info_t phy_info;
} nb_radio_info_t;



/**
 * @brief 指示芯片是否从深睡唤醒的，常用于支持深睡的模式，以识别是否为正常唤醒状态
 * 
 * @return bool
 * @note ZOS_EOK:深睡眠唤醒    ZOS_ERROR：非深睡眠唤醒
 */
extern zos_err_t nb_get_powenon_from_deepsleep(void);

/**
 * @brief 获取开机类型
 *
 * @return 开机类型返回值如下： * 
 *  NB_STATE_POWER_ON = 0,  ///  正常开机
 *  NB_STATE_PIN_RESET,     ///  RESET硬件复位
 *  NB_STATE_SOFT_RESET,    ///  软件复位
 *  NB_STATE_UTC_WAKEUP,    ///  RTC超时唤醒
 *  NB_STATE_EXTPIN_WAKEUP, ///  WAKEUP-PIN 唤醒
 *  NB_STATE_WDT_RESET,     ///  硬件看门狗复位
 *  NB_STATE_UNKNOWN_ON,    ///  未知错误，请查看硬件设计
 */
extern uint32_t nb_get_power_type(void);


/**
 * @brief 获取复位类型
 * 
 * @return 复位类型如下 :
 *   NB_RB_BY_ASSERT = 0,	//ASSERT断言错误复位
 *   NB_RB_BY_NRB,			//软件复位 来自AT+NRB/nb_reboot/....
 *   NB_RB_BY_RESET,			//软件复位 来自恢复出厂设置 AT+RESET
 *   NB_RB_BY_POWERTEST,		//软件复位 by	AT+NV=POWERTEST,unused
 *   NB_RB_BY_FOTA,			//软件复位 by  FOTA
 *   NB_RB_BY_LOW_VOL,		//低电压复位 by nb_vbat_low_check for low vBAT
 */
extern uint32_t nb_get_reset_type(void);


/**
 * @brief  关闭standby浅睡模式，接口内部实现了累加操作，以供多外设配对使用。
 * 
 * @warning 由于平台默认开启standby睡眠功能，所以当客户使用外设时，由于standby期间会关闭外设时钟，所以需要临时关闭standby睡眠，以防止丢数据。
 * 
 *  该接口必须配对使用，即在准备使用外设时调用nb_standby_lock()关闭standby,使用完毕外设时调用nb_standby_unlock()开启standby。
 * 
 * @attention  由于存在多个外设同时工作情况，进而要求必须配对开关standby，否则会影响其他外设工作
 */
extern void nb_standby_lock(void);

/**
 * @brief  打开standby浅睡模式，接口内部实现了累减操作，以供多外设配对使用。
 * 
 * @warning 注意平台默认开启standby睡眠功能，当客户使用外设时，由于standby期间会关闭外设时钟，所以需要临时关闭standby睡眠，以防止丢数据。
 * 
 *  该接口必须配对使用，即在准备使用外设时调用nb_standby_lock()关闭standby,使用完毕外设时调用nb_standby_unlock()开启standby。
 * 
 * @attention  由于存在多个外设同时工作情况，进而要求必须配对开关standby，否则会影响其他外设工作
 */
extern void nb_standby_unlock(void);

/*
 * @brief 强制进入standby睡眠
 *
 * @warning  该接口慎用！强行清空计数，可能会造成正在工作的外设因为进了standby睡眠而数据通信异常。
 */
extern void nb_standby_clear(void);


/**
 * @brief 关闭deepsleep 深睡模式(关闭PSM模式)
 * 
 * @warning 必须与 nb_work_unlock配对使用，否则会造成深睡异常
 * 
 * @note  理论存在多个任务冲突使用芯翼芯片的可能，只要每个业务配对使用工作锁，就可以保证流程正常
 */
extern void nb_work_lock(void);

/**
 * @brief  打开deepsleep 深睡模式(打开PSM模式)
 * 
 * @attention  注意 : QS-100模组的深睡条件是没有用户申请锁的前提下，若内部检测出超过2秒的空闲时间，就会进入深睡； \n
 *  所以，并不是说用户释放锁后，就会很快睡眠，还要取决于3GPP能否调度出2秒以上的空闲，例如若在1.28S的寻呼状态下，永远都不会进入深睡。
 * 
 * @note  如果用户确定整机无需继续工作，且下次上电后重新执行attach流程，可以使用nb_fast_power_off来更快速深睡，类似直接断电，做到一秒内进深睡。
 * 
 * @warning 必须与nb_work_lock配套使用，否则可能造成其他业务因为提前深睡而造成流程异常。\n
 * 
 *  默认释放锁后内部会通过PS触发RAI，如果用户想自行控制RAI的发送类型和发送时机，将出厂NV参数close_rai设为1即可。
 */
extern void nb_work_unlock(void);

/**
 * @brief 强制芯片进入深睡
 * 
 * 注意下次上电后会重新执行驻网流程。
 *
 * @warning 该接口不与基站进行握手通信，类似直接断电，可达到1秒内进深睡。仅能在两个场景下使用：
 * 1) 当用户启用的软件看门狗超时后，可以认为当前3GPP状态异常，调用该接口进行强制深睡.\n
 * 2) 部分客户为了健壮性考虑，要求不使用PSM模式，每次工作完毕后，调用该接口快速秒级深睡，下次再上电执行attach流程.
 */
extern void nb_fast_power_off(void);

/**
 * @brief 模组软重启接口
 * 
 * @attention 软重启后RTC定时器及当前世界时间保持不变，若重启前已经获取了当前世界时间，则重启后仍然有效
 */
extern void nb_reboot(void);


/**
 * @brief 			进入或退出飞行模式
 * @param status  	0:进入飞行模式    1:退出飞行模式
 * 
 * @warning         关闭飞行模式后不代表联网成功，需要使用联网指令查询网络信息，确定联网成功才可以做网络业务。
 * 
 * @return 			ZOS_EOK:设置成功    ZOS_ERROR:设置失败
 */
extern zos_err_t nb_set_cfun(int status);


/**
 * @brief           查询当前是否在飞行模式
 * @param  cfun     存储cfun状态的int指针    0:进入飞行模式    1:退出飞行模式
 * 
 * @return          ZOS_ERROR:获取失败, ZOS_OK:获取成功
 */
extern zos_err_t nb_get_cfun(int *cfun);

/**
 * @brief 			获取PDP 上下文激活状态
 * @param cgact		存储cgact的int指针   0:未激活   1:已激活，可以做网络业务
 *
 * @return			ZOS_ERROR:获取失败, ZOS_OK:获取成功
 */
extern zos_err_t nb_get_CGACT(int *cgact);

/**
 * @brief 			查询EPS网络注册状态
 * @param cereg		存储cereg的int指针，获取成功时，该值的具体含义如下：
 * 					0 未注册，当前 MT 没有搜寻一个新的运营商进行注册
 * 					1 注册，本地网络
 * 					2 未注册，当前 MT 正在搜寻一个新的运营商进行注册
 * 					3 注册被拒绝
 * 					4 未知
 * 					5 已注册，漫游
 * 
 * @return			ZOS_ERROR:获取失败, ZOS_OK:获取成功
 * 
 */
extern zos_err_t nb_get_cereg(int *cereg);

/**
 * @brief 			获取模组SN编号
 * @param sn		SN数据存储首地址
 * @param len		入参sn指针的长度，
 * 
 * @return			ZOS_ERROR:获取失败, ZOS_OK:获取成功
 */
extern zos_err_t nb_get_SN(char *sn, int len);

/**
 * @brief 			获取信号强度
 * @param rssi		存储rssi的int指针,  0-31:信号范围    99:无信号
 * 
 * @return			ZOS_ERROR:获取失败, ZOS_OK:获取成功
 */
extern zos_err_t nb_get_csq(int *rssi);

/**
 * @brief			获取模组IMEI识别号
 * @param imei		存储imei的数组首地址，数组长度不能小于16
 * 
 * @return 			ZOS_ERROR:获取失败, ZOS_OK:获取成功
 */
extern zos_err_t nb_get_IMEI(char *imei);

/**
 * @brief			获取模组IMSI
 * @param imsi		存储imsi的数组首地址，数组长度不能小于16
 * 
 * @warning         若尚未检测到SIM卡，imsi指针未被赋值，需要客户自行识别是否已经识别到SIM卡
 * 
 * @return 			ZOS_ERROR:获取失败, ZOS_OK:获取成功
 */
extern zos_err_t nb_get_IMSI(char *imsi);

/**
 * @brief			获取当前驻网小区ID
 * @param 			存储cellid的int指针
 * 
 * @warning         小区未驻留之前，无法获取小区ID
 * 
 * @return			ZOS_ERROR:获取失败, ZOS_OK:获取成功
 */
extern zos_err_t nb_get_CELLID(int *cell_id);

/**
 * @brief 			获取SIM卡 ICCID号码
 * @param ccid      用来存储ccid的数组首地址，数组长度不得低于23
 * 
 * @warning         注意入参内存申请长度，否则会造成内存越界
 *                  若尚未检测到SIM卡，ccid指针未被赋值，需要客户自行识别是否已经识别到SIM卡
 * 
 * @return			ZOS_ERROR:获取失败, ZOS_OK:获取成功
 */
extern zos_err_t nb_get_NCCID(char *ccid);

/**
 * @brief 			获取当前APN
 * @param apn_buf	用来存储APN的数组首地址
 * @param len		入参apn_buf指针的长度，由调用者赋值，但不能小于100
 * @param query_cid	PDP激活对应的哪一路cid，调用者若不关心则填-1，接口内部会自动赋值，即当前网络激活承载的cid路数，一般为0
 * 
 * @warning         注意入参内存申请长度，否则会造成内存越界
 *                  若尚未配置APN，apn_buf不会被赋值
 					若query_cid要在驻网之后才能填-1，否则返回空
 *
 * @return			ZOS_ERROR:获取失败, ZOS_OK:获取成功
 */
extern zos_err_t nb_get_PDP_APN(char *apn_buf, int len, int query_cid);

/**
 * @brief			获取当前网络激活承载的为哪路cid，PDP未激活时默认-1
 * 
 * @return 			当前网络激活承载的为哪路cid，默认值为0
 */
extern zos_err_t nb_get_working_cid();

/**
 * @brief 			获取模块当前的IP地址
 * @param ipAddr	用来存储IP地址的数组首地址
 * @param addrLen	入参ipAddr指针的长度，由调用者赋值，但不能小于17
 *
 * @warning         注意入参内存申请长度，否则会造成内存越界
 *                  若尚未PDP激活成功，ipAddr不会被赋值
 * 
 * @note            该接口得到的是字符串类型地址，如需要转成int型，需要自行调用int_aton接口
 * 
 *  @return 		ZOS_ERROR:获取失败, ZOS_OK:获取成功
 */
extern zos_err_t nb_getIP4Addr(char *ipAddr, int addrLen);

/**
 * @brief 			获取IPV4的整形地址
 * @param ip4addr	存储ip4addr的unsigned int指针
 * 
 * @warning         若尚未PDP激活成功，返回ZOS_ERROR
 * 
 * @return 		ZOS_ERROR:获取失败, ZOS_OK:获取成功
 */
extern zos_err_t nb_get_ip4addr(unsigned int *ip4addr);

/**
 * @brief 			获取 3412 tau 时间
 * @param tau		存储tau的int指针
 * 
 * @return			ZOS_ERROR:获取失败, ZOS_OK:获取成功
 */
extern zos_err_t nb_get_T_TAU(int *tau);

/**
 * @brief 			获取 3324 act 时间
 * @param t3324		存储t3324的int指针
 * 
 * @return			ZOS_ERROR:获取失败, ZOS_OK:获取成功
 */
extern zos_err_t nb_get_T_ACT(int *t3324);

/**
 * @brief 		用户快速链接释放(用来通知PS发送空的UDP报文，并携带RAI指示给基站,以快速释放链接)
 * 
 * @note        当用户认为后续没有报文交互需求时，调用该接口来伴随触发RAI，以降低功耗。必须设置出厂NV参数close_rai为1，否则在用户释放最后一把锁后会由QS-100模组自触发RAI
 * 
 * @warning     该接口慎用！！！建议用户使用如cis_ext_send_with_rai、cdp_send_syn_with_rai等接口\n
 *    PS会释放当前待发送的所有上行数据，进行需要用户确保调用该接口时已经没有待发送的上行数据。
 * 
 * @return		ZOS_ERROR:发送失败, ZOS_OK:发送成功
 */
extern zos_err_t nb_send_rai();

/**
 * @brief   获取厂商信息
 * 
 * @param   modul_ver  存储modul_ver的内存buf，由调用者分配，buf长度不小于20；
 * @param   len     modul_ver的内存长度，不小于20
 * 
 * @return 	ZOS_ERROR:获取失败, ZOS_OK:获取成功
**/
extern zos_err_t nb_get_MODULVER(char *modul_ver, int len);

/**
 * @brief   获取软件版本号
 * 
 * @param   versionExt  存储versionExt的内存buf，由调用者分配，buf长度不小于28
 * @param   len   versionExt的内存长度，不小于28
 * 
 * @return 	ZOS_ERROR:获取失败, ZOS_OK:获取成功
**/
extern zos_err_t nb_get_VERSIONEXT(char *versionExt, int len);

/**
 * @brief   获取硬件版本号
 * 
 * @param   hardver  存储hardver的内存buf，由调用者分配，buf长度不小于20；
 * @param   len    hardver的内存长度，不小于20
 * 
 * @return 	ZOS_ERROR:获取失败, ZOS_OK:获取成功
**/
extern zos_err_t nb_get_HARDVER(char *hardver, int len);

/**
 * @brief   获取运营商类型
 * @param   uicc_type  存储uicc_type的int 指针,运营商类型如下: 
 * 			NB_SIM_TYPE_TELECOM :电信   
 * 			NB_SIM_TYPE_MOBILE : 移动   
 * 			NB_SIM_TYPE_UNICOM : 联通	
 * 
 * @return 	ZOS_ERROR:获取失败, ZOS_OK:获取成功
*/
extern zos_err_t nb_get_SIM_TYPE(int *sim_type);

/**
 * @brief   获取eDRX的寻呼周期和寻呼窗口周期大小
 * 
 * @param   eDRX_value	eDRX的寻呼周期，单位秒
 * @param   ptw_value	寻呼窗口周期，单位秒
 * 
 * @return  ZOS_ERROR:获取失败, ZOS_OK:获取成功
*/
extern zos_err_t nb_get_eDRX_value(float *eDRX_value, float *ptw_value);

/**
 * @brief 	获取服务小区信息(对应AT命令为AT+NUESTATS=RADIO)
 * @param rcv_servingcell_info 用户主动zos_malloc，并将地址传递进来，不可为NULL
 * 
 * @return  ZOS_ERROR:获取失败, ZOS_OK:获取成功
 */
extern zos_err_t nb_get_servingcell_info(nb_serving_cell_info_t *rcv_servingcell_info);

/**
 * @brief 	获取邻小区信息(对应AT命令为AT+NUESTATS=CELL)
 * @param neighbor_cell_info 用户主动zos_malloc，并将地址传递进来，不可为NULL
 * 
 * @note 获取邻小区的earfcn，pci，rsrp与邻小区的数量，最多只返回5个邻小区的信息。
 * 
 * @return ZOS_ERROR:获取失败, ZOS_OK:获取成功
 */
extern zos_err_t nb_get_neighborcell_info(nb_neighbor_cell_info_t *neighbor_cell_info);

/**
 * @brief 	获取PHY信息	(对应AT命令为AT+NUESTATS=BLER和AT+NUESTATS=THP)
 * @param  rcv_phy_info 用户主动zos_malloc，并将地址传递进来，不可为NULL
 * 
 * @return ZOS_ERROR:获取失败, ZOS_OK:获取成功
 */
extern zos_err_t nb_get_phy_info(nb_phy_info_t *rcv_phy_info);

/**
 * @brief 	获取NUESTATS相关信息
 * @param rcv_radio_info 用户主动zos_malloc，并将地址传递进来，不可为NULL
 * 
 * @note  该接口内部分为几次发送不同的AT命令给PS，由于这条AT命令非标准，存在变化的可能，客户自行参考该DEMO实现即可
 * 
 * @return ZOS_ERROR:获取失败, ZOS_OK:获取成功
 */
extern zos_err_t nb_get_radio_info(nb_radio_info_t *rcv_radio_info);

/**
 * @brief 	检查当前电量是否充足
 * 
 * @return ZOS_OK:电量充足   ZOS_ERROR:电量不足
 */
extern zos_err_t nb_vbat_low_check(void);




#endif  /* __NB_H_ */
